package ar.edu.isft189.utility;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DBUtility {
	private static Connection c = null;
	private static org.firebirdsql.pool.FBWrappingDataSource dataSource = null;
	// private static String filesep = System.getProperty("file.separator");

	// private static String databaseURL = "localhost/3050:C:" + filesep +
	// "SGANS" + filesep + "isft.fdb";
	private static String databaseURL = null;
	private static String dbDescription = null; // "An Example Database";
	private static String user = null; // "sysdba";
	private static String password = null; // = "masterkey";
	private static String rol = null; // = "sysdb";
	private static int loginTimeOut = 0; // = 10; // 10 segundos de time-out
											// para login
	private static java.sql.DatabaseMetaData dbMetaData = null;

	public static Connection getConnection() {
		if (c != null)
			return c;
		else {
			try {
				if (c == null) {
					// Obtengo las propiedades del archivo de configuracion
					leerProperies();

					dataSource = new org.firebirdsql.pool.FBWrappingDataSource();

					System.out.println("Me conecto!");
					// Set the standard properties
					dataSource.setDatabase(databaseURL);
					dataSource.setDescription(dbDescription);
					dataSource.setRoleName(rol);
					dataSource.setLoginTimeout(loginTimeOut);
					c = dataSource.getConnection(user, password);

					System.out.println("Connection established.");
					c.setAutoCommit(false);
					System.out.println("Auto-commit is disabled.");
					dbMetaData = c.getMetaData();
					// Ok, let's query a driver/database capability
					if (dbMetaData.supportsTransactions()) {
						System.out.println("Transactions are supported.");
					} else {
						System.out.println("Transactions are not supported.");
					}
				} else {
					System.out.println("Ya estaba conectado!");
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return c;
		}
	}

	/**
	 * @author david
	 * 
	 *         Metodo que retorna el directorio donde esta la base de datos para
	 *         que use la aplicacion, leyendolo desde un archivo properties
	 */
	private static void leerProperies() {

		/** Creamos un Objeto de tipo Properties */
		Properties propiedades = new Properties();
		/** Cargamos el archivo desde la ruta especificada */
		try {
			propiedades.load(new FileInputStream("syscfg/dbConfig.properties"));
			/** Obtenemos los parametros definidos en el archivo */
			databaseURL = propiedades.getProperty("url");
			dbDescription = propiedades.getProperty("dbDescription");
			user = propiedades.getProperty("user");
			password = propiedades.getProperty("password");
			rol = propiedades.getProperty("rol");
			loginTimeOut = Integer.parseInt(propiedades
					.getProperty("loginTimeOut"));
		} catch (IOException e) {
			System.err.println("Error en seteo de valores del archivo Properties");
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * Metodo que permite la ejecucion de un query de actualizacion
	 * (insert,update,delete) sobre la b.d. <b>No realiza commit, esto debe
	 * hacerse cuando corresponda llamando al metodo doCommit()</b>
	 * 
	 * @param query
	 *            query sql a ejecutar
	 * @return true si se ejecuto ok, false en caso de error
	 */
	public static boolean executeQuery(final String query) {
		boolean r = false;
		try {
			Statement ss = c.createStatement();
			ss.executeUpdate(query); // update, insert, delete, etc.
			 r = true;
		} catch (SQLException e) {
			System.err.println("Error from executeQuery");
			e.printStackTrace();
		}
		return r;
	}

	/**
	 * 
	 * Metodo que que permite la ejecucion de un query de consulta (select)
	 * sobre la b.d. el cual devuelve un ResultSet que puede ser recorrido para
	 * recuperar cada una de las tuplas devueltas
	 * 
	 * @param query
	 *            query sql a ejecutar
	 * @return ResultSet con tuplas a recuperar si todo Ok o null en caso de
	 *         error
	 */
	public static ResultSet getResultSet(final String query) {
		ResultSet rrs = null;
		try {
			Statement ss = c.createStatement();
			rrs = ss.executeQuery(query); // select
		} catch (SQLException e) {
			System.err.println("Unable to get ResultSet from [" + query + "]");
			e.printStackTrace();
		}
		return rrs;
	}

	public static CallableStatement prepareExePro(String procedure) {
		CallableStatement cs = null;
		try {
			cs = c.prepareCall(procedure);
		} catch (SQLException e) {
			System.err
					.println("DataIO.prepareExePro():Unable to prepare Procedure ");
			e.printStackTrace();
		}
		return cs;
	}

	public static ResultSet executePro(String procedure, CallableStatement cs) {
		ResultSet rs = null;
		try {
			rs = cs.executeQuery();
		} catch (SQLException e) {
			System.err
					.println("DataIO.executePro():Unable to execute Procedure : " + procedure);
			e.printStackTrace();
		}
		return rs;
	}
	
	/**
	 * 
	 * Metodo que que realiza commit en b.d. para dar por aceptado los ultimos
	 * cambios realizados sobre la b.d.
	 * 
	 * @return true si se ejecuto ok, false en caso de error
	 */
	public static synchronized boolean doCommit() {
		boolean r = false;
		try {
			c.commit();
			 r = true;
		} catch (SQLException e) {
			System.err.println("Error from doCommit");
			e.printStackTrace();			
		}
		return r;
	}


}
